package com.zhaosc.configbean;

import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.zhaos.cluster.Cluster;
import com.zhaosc.invoke.HttpInvoke;
import com.zhaosc.invoke.Invoke;
import com.zhaosc.loadbalance.LoadBalance;
import com.zhaosc.proxy.advice.InvokeInvocationHandler;
import com.zhaosc.registry.BaseRegistryDelegate;

public class Reference extends BaseConfigBean implements FactoryBean ,InitializingBean,ApplicationContextAware{

	/**
	 * 
	 */
	private static final long serialVersionUID = -4975866894148881867L;

	private String interf;
	
	private String loadBalance;
	
	private String protocol;
	
	private static ApplicationContext application;
	
	private Invoke invoke;
	
    private String cluster;
    
    private String retries;
    
    private static Map<String, Cluster> clusters = new HashMap<String, Cluster>();
	
	private static Map<String,Invoke> invokes=new HashMap<String,Invoke>(); 
	
    private static Map<String, LoadBalance> loadBalances = new HashMap<String, LoadBalance>();
    
    private List<String> registryInfo=new ArrayList<String>();
    
    static{
        invokes.put("http", new HttpInvoke());
//        invokes.put("rmi", null);
//        
//        loadBalances.put("romdom", new RandomLoadBalance());
//        loadBalances.put("roundrob", new RoundRobinLoadBalance());
    }

	public String getInterf() {
		return interf;
	}

	public void setInterf(String interf) {
		this.interf = interf;
	}

	public String getLoadBalance() {
		return loadBalance;
	}

	public void setLoadBalance(String loadBalance) {
		this.loadBalance = loadBalance;
	}

	public String getProtocol() {
		return protocol;
	}

	public void setProtocol(String protocol) {
		this.protocol = protocol;
	}

	public static ApplicationContext getApplication() {
		return application;
	}

	public static void setApplication(ApplicationContext application) {
		Reference.application = application;
	}

	public Invoke getInvoke() {
		return invoke;
	}

	public void setInvoke(Invoke invoke) {
		this.invoke = invoke;
	}

	public static Map<String, Invoke> getInvokes() {
		return invokes;
	}

	public static void setInvokes(Map<String, Invoke> invokes) {
		Reference.invokes = invokes;
	}

	public static Map<String, LoadBalance> getLoadBalances() {
		return loadBalances;
	}

	public static void setLoadBalances(Map<String, LoadBalance> loadBalances) {
		Reference.loadBalances = loadBalances;
	}

	public List<String> getRegistryInfo() {
		return registryInfo;
	}

	public void setRegistryInfo(List<String> registryInfo) {
		this.registryInfo = registryInfo;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		Reference.application=applicationContext;
		
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		registryInfo=BaseRegistryDelegate.getRegistry(getId(), application);
		 System.out.println(registryInfo);
		
	}

	@Override
	public Object getObject() throws Exception {
		   System.out.println("Reference! getObject");
		   if(protocol!=null&&!"".equals(protocol)){
			   invoke=invokes.get(protocol);
		   }else{
			   Protocol protocol=application.getBean(Protocol.class);
			   if(protocol!=null){
				   invoke=invokes.get(protocol.getName());
			   }else{
				   invoke=invokes.get("htpp");
			   }
		   }
		   
		return Proxy.newProxyInstance(this.getClass().getClassLoader(),
				new Class<?>[] {Class.forName(interf)},
				new InvokeInvocationHandler(invoke, this));
	}

	@Override
	public Class getObjectType() {
		try {
			if(interf!=null&&!"".equals(interf)){
				return Class.forName(interf);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} 
		
		return null;
	}

	@Override
	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return false;
	}
	
    public String getCluster() {
        return cluster;
    }
    
    public void setCluster(String cluster) {
        this.cluster = cluster;
    }
    
    public String getRetries() {
        return retries;
    }
    
    public void setRetries(String retries) {
        this.retries = retries;
    }
    public static Map<String, Cluster> getClusters() {
        return clusters;
    }
    
    public static void setClusters(Map<String, Cluster> clusters) {
        Reference.clusters = clusters;
    }
    
    
}
